/*
 * Copyright (c) 2006-2018, RT-Thread Development Team
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Change Logs:
 * Date           Author       Notes
 * 2019-09-22     Warfalcon    first version
 */


static unsigned long int  crc_tab[256];

static unsigned long int bitrev(unsigned long int poly, unsigned long int width)
{
    unsigned long int i;
    unsigned long int var = 0;

    for (i = 0; i < width; i++)
    {
        if (poly & 0x00000001)
            var |= 1 << (width - 1 - i);

        poly >>= 1;
    }
    return var;
}

static void crc32_table_init(unsigned long int poly)
{
    unsigned long int i, j;
    unsigned long int c;

    poly = bitrev(poly, 32);

    for (i = 0; i < 256; i++)
    {
        c = i;

        for (j = 0; j < 8; j++)
        {
            if(c & 0x00000001)
                c = poly ^ (c >> 1);
            else
                c >>= 1;
        }

        crc_tab[i] = c;
    }
}

static unsigned long int crc32(unsigned long int crc_init, unsigned char *buf, unsigned long int len)
{
    unsigned long int i;
    unsigned char index;

    for (i = 0; i < len; i++)
    {
        index = (unsigned char)(crc_init ^ buf[i]);
        crc_init = (crc_init >> 8) ^ crc_tab[index];
    }

    return crc_init;
}

//unsigned long int crc_single_calculate(unsigned char *buf, unsigned long int len)
//{
//	unsigned long int crc_init = 0xffffffff;

//	crc_init = crc32(crc_init, buf, len) ^ 0xffffffff;
//
//	return crc_init;
//}

unsigned long int crc_accumulated_calculate(unsigned long int crc_init, unsigned char *buf, unsigned long int len)
{
    crc_init = crc32(crc_init, buf, len) ;

    return crc_init;
}

void CRC32InitFun(void)
{
#define POLYNOMIAL		0x04c11db7

    crc32_table_init(POLYNOMIAL);

}


